<?php
/**
 * This file defines the {@see \BF\Config\Writer\Xml} class.
 *
 * @author     Ulf Kadner <ulfikado@gmail.com>
 * @category   Beluga_Framework
 * @copyright  (c) 2014, Ulf Kadner
 * @package    Config
 * @since      2014-12-27
 * @subpackage Writer
 * @version    1.0.0
 */

namespace BF\Config\Writer
{

   require_once \dirname( __DIR__ ) . '/IWriter.interface.php';

   /**
    * @since      v0.1
    */
   class Xml implements \BF\Config\IWriter
   {

      # <editor-fold defaultstate="collapsed" desc=" - - -   P R I V A T E   F I E L D S   - - - - - - - - - - - - - - - - - - - - - -">

      /**
       * The path of XML config file
       *
       * @var string
       */
      private $file;

      /**
       * The name of the root element, containing the configuration data.
       *
       * @var string
       */
      private $rootElementName;

      /**
       * The name of the XML element, defining a single config value.
       *
       * @var string
       */
      private $configElementName;

      /**
       * @var \BF\Config\IReader
       */
      private $reader;

      # </editor-fold>

      # <editor-fold defaultstate="collapsed" desc=" - - >   P U B L I C   C O N S T R U C T O R   - - - - - - - - - - - - - - - - - -">

      /**
       * Inits a new instance.
       *
       * @param  \BF\Config\IReader $reader Optional associated config reader.
       * @param  string $file               The path of XML config file
       * @param  string $rootElementName    The name of the root element, containing the configuration data. (default='Configs')
       * @param  string $configElementName  The name of the XML element, defining a single config value. (default='Config')
       * @throws \BF\ArgumentException
       * @throws \BF\IO\FileFormatException
       */
      public function __construct(
         \BF\Config\IReader $reader = null, $file = null, $rootElementName = 'Configs', $configElementName = 'Config' )
      {
         $this->reader = $reader;
         if ( \is_null( $reader ) )
         {
            if ( empty( $file ) )
            {
               throw new \BF\ArgumentException(
                  'file', $file, 'No file defined to init a XML config writer!'
               );
            }
            $this->reader            = new \BF\Config\Reader\Xml( $file, $rootElementName, $configElementName );
            $this->file              = $file;
            $this->rootElementName   = $rootElementName;
            $this->configElementName = $configElementName;
            return;
         }
         if ( empty( $file ) )
         {
            $options = $this->reader->getOptions();
            if ( ! isset( $options[ 'file' ] ) )
            {
               throw new \BF\IO\FileFormatException(
                  $file, 'No file defined to init a XML config writer!'
               );
            }
            $file = $options[ 'file' ];
         }
         $this->file              = $file;
         $this->rootElementName   = $rootElementName;
         $this->configElementName = $configElementName;
      }

      # </editor-fold>

      # <editor-fold defaultstate="collapsed" desc=" - - -   P U B L I C   M E T H O D S   - - - - - - - - - - - - - - - - - - - - - -">

      /**
       * Returns if writing to current source can be used.
       *
       * @return boolean
       */
      public function canWrite()
      {
          return ! empty( $this->file );
      }

      /**
       * Returns all current defined writer options as a associative array. The used options are 'file',
       * 'rootElementName' and 'configElementName'.
       *
       * @return array
       */
      public function getOptions()
      {
         return array(
            'file'              => $this->file,
            'rootElementName'   => $this->rootElementName,
            'configElementName' => $this->configElementName
         );
      }

      /**
       * Returns a config data reader of current source.
       *
       * @return \BF\Config\IReader
       */
      public function getReader()
      {
         return $this->reader;
      }

      /**
       * Writes all defined config values to based source.
       *
       * @param  \BF\Config\ValueCollection $configValues All config values to write.
       * @return boolean TRUE on success, FALSE otherwise.
       */
      public function write( \BF\Config\ValueCollection $configValues )
      {
         $this->reader->reload();
         $currentValues = $this->reader->readAll()->toArray();
         $confValues    = $configValues->toArray();
         foreach ( $confValues as $cname => $cvalue )
         {
             $currentValues[ $cname ] = $cvalue;
         }
         $w = new \XMLWriter();
         $w->openUri( $this->file );
         $w->setIndent( true );
         $w->setIndentString( '  ' );
         $w->startDocument( '1.0', 'utf-8' );
         $w->startElement( $this->rootElementName ); // <Configs>
         foreach ( $currentValues as $value )
         {
             $w->startElement( $this->configElementName ); // <Config ...>
             $w->writeAttribute( 'name',   $value->name );
             $w->writeAttribute( 'type',   $value->type );
             $w->writeAttribute( 'strict', $value->isstrict ? '1' : '0' );
             $w->text( (string) $value );
             $w->endElement(); // </Config>
         }
         $w->endElement(); // </Configs>
         $w->endDocument();
         $w->flush();
         $w = null;
      }

      # </editor-fold>

   }

}

